import os
import re
import json
import sqlite3

from PyQt5 import QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.Qt import QFrame, QAction, QFont, pyqtSlot, QShortcut, QIcon, QPixmap, QSize, QPushButton, QTimer

from .BaseWindow import BaseWindow
from ..ui_utils import read_conf, write_conf, restart_app
from .._config import UI_RES_PATH, BASE_PATH


class UiBaseSettings(QFrame, BaseWindow):
    def __init__(self, page: int=None, conf: str='', db: str=''):
        self.conf = conf
        self.page_sum = 9  # 页数
        self.changed_keys = {}  # 用户改动后的参数
        self.ui_buffer = None  # 挂载UI主页面中的Queue
        self.cam_conf_path = BASE_PATH  # 相机配置文件路径
        self.db_path = db  # 数据库路径

        super(UiBaseSettings, self).__init__()

        if page != None:
            self.sidebar.setVisible(False)
            self.grid_main.setColumnStretch(0, 0)
            self.content.setCurrentIndex(page)

        if conf:
            self._initConf()
            self._overwrite(read_conf(self.conf))

        self.standard_keys = ['UI_KEY_STD_']
        self.setFixedSize(630, 750)
        self.setWindowTitle('设置')

    def showEvent(self, event):
        self.SetWindowCentered()
        # 初始化数据库
        if os.path.exists(self.db_path):
            self.conn = sqlite3.connect(str(self.db_path))
            self.cursor = self.conn.cursor()
            self.std_query()
        if self.windowTitle() == '相机调试':
            self._cam_debug()
        # self._overwrite(read_conf(self.conf))

    def closeEvent(self, event):
        if os.path.exists(self.db_path):
            self.conn.close()
        change_flag = self._if_change()
        if change_flag:
            reply = QtWidgets.QMessageBox.information(self, '提示', '是否保存当前设置？', QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
            if reply == QtWidgets.QMessageBox.Yes:
                self._save()
            else:
                self.close()

    def _connect(self):
        self.sidebar.itemClicked.connect(self.__change_content)
        self.BTN_SAVE.clicked.connect(self._save)
        self.BTN_CAM_SAVE.clicked.connect(self.cam_save)
        self.BTN_CAM_RESET.clicked.connect(self.cam_reset)
        self.BTN_CANCEL.clicked.connect(self.close)

        # 标准 增删改
        # self.BTN_STD_SAVE.clicked.connect(self.std_save)
        # self.BTN_STD_LOAD.clicked.connect(self.std_load)
        # self.BTN_STD_DEL.clicked.connect(self.std_del)
        # self.STANDARD_NAME_LIST.activated.connect(self.std_query)

        QShortcut('Esc', self).activated.connect(self.close)

    @pyqtSlot(QtWidgets.QTreeWidgetItem)
    def __change_content(self, item):
        if item == self.tree_item_0:
            self.content.setCurrentWidget(self.page_0)
        elif item == self.tree_item_1:
            self.content.setCurrentWidget(self.page_8)
        elif item == self.tree_item_1_0:
            self.content.setCurrentWidget(self.page_1)
        elif item == self.tree_item_1_1:
            self.content.setCurrentWidget(self.page_2)
        elif item == self.tree_item_1_2:
            self.content.setCurrentWidget(self.page_3)
        elif item == self.tree_item_2:
            self.content.setCurrentWidget(self.page_4)
        elif item == self.tree_item_3:
            self.content.setCurrentWidget(self.page_5)

    def _initUI(self):
        def __QTreeItem(i, var, txt, parent):
            item_name = 'tree_item_%s' % var
            setattr(self, item_name, QtWidgets.QTreeWidgetItem(self.__dict__[parent]))
            item_obj: QtWidgets.QTreeWidgetItem = getattr(self, item_name)
            item_obj.setIcon(0, QIcon(str(UI_RES_PATH / 'set.png')))
            self.sidebar.addTopLevelItem(item_obj)
            self.sidebar.topLevelItem(i).setText(0, txt)
            font = QFont()
            font.setBold(True)
            font.setPointSize(15)
            self.sidebar.topLevelItem(i).setFont(0, font)
        def __QTreeChild(i, var, txt, parent):
            item_name = 'tree_item_%s_%s' % (parent, var)
            parent = 'tree_item_%s' % parent
            setattr(self, item_name, QtWidgets.QTreeWidgetItem(self.__dict__[parent]))
            item_obj: QtWidgets.QTreeWidgetItem = getattr(self, item_name)
            self.__dict__[parent].addChild(item_obj)
            self.__dict__[parent].child(i).setText(0, txt)
            font = QFont()
            font.setBold(True)
            self.__dict__[parent].child(i).setFont(0, font)
        def __QStackedPage(var):
            page_name = 'page_%s' % var
            setattr(self, page_name, QtWidgets.QWidget())
            page_obj: QtWidgets.QWidget = getattr(self, page_name)
            grid_name = 'grid_page_%s' % var
            setattr(self, grid_name, QtWidgets.QGridLayout(page_obj))
            grid_obj: QtWidgets.QGridLayout = getattr(self, grid_name)

            scroll_obj, parent, grid_scroll_obj = self.QScrollAreaPack(var, page_obj)

            __QStackedPageContent(var, parent, grid_scroll_obj)

            grid_obj.addWidget(scroll_obj, 0, 0)

            self.content.addWidget(page_obj)
        def __QStackedPageContent(var, parent, grid):
            if isinstance(var, int):
                func_obj = getattr(self, 'p%d_custom' % var)
                func_obj(parent, grid)
            else:
                pass


        self.grid_main = QtWidgets.QGridLayout(self)


        self.sidebar = QtWidgets.QTreeWidget(self)
        # self.sidebar.headerItem().setText(0, '设置')
        self.sidebar.headerItem().setHidden(True)

        self.tree_item_0: QtWidgets.QTreeWidgetItem
        for i, (var, txt, parent) in enumerate([
                ('', '通用', 'sidebar'),
                ('', '检测', 'sidebar'),
                ('', '标准', 'sidebar'),
                ('', '硬件', 'sidebar'),
        ]):
            var = str(i) if not var else var
            __QTreeItem(i, var, txt, parent)
        self.tree_item_1_0: QtWidgets.QTreeWidgetItem
        for i, (var, txt, parent) in enumerate([
                ('', '模型0', 1),
                ('', '模型1', 1),
                ('', '模型2', 1),
        ]):
            var = str(i) if not var else var
            __QTreeChild(i, var, txt, parent)
        self.sidebar.setCurrentItem(self.tree_item_0)


        self.content = QtWidgets.QStackedWidget(self)
        self.content.setFrameShape(self.StyledPanel)
        self.content.setCurrentIndex(0)

        self.page_0: QtWidgets.QWidget
        for var in range(self.page_sum):
            __QStackedPage(var)


        self.layout_btn = QtWidgets.QHBoxLayout()
        icon = QIcon()
        icon.addPixmap(QPixmap(str(UI_RES_PATH / 'help.png')))
        self.BTN_HELP = QtWidgets.QPushButton(icon, '', self)
        self.BTN_HELP.setFlat(True)
        self.BTN_HELP.setIconSize(QSize(30, 30))
        self.BTN_HELP.setFixedWidth(35)
        self.layout_btn.addWidget(self.BTN_HELP)
        self.layout_btn.addItem(QtWidgets.QSpacerItem(1, 1))
        self.layout_btn.setStretch(1, 5)
        for (var, txt) in [
                ('save', '保存'),
                ('cancel', '取消'),
                # ('apply', '应用'),
                # ('reset', '重置'),
        ]:
            btn_name = 'BTN_' + var.upper()
            setattr(self, btn_name, QtWidgets.QPushButton(self))
            self.__dict__[btn_name].setText(txt)
            self.__dict__[btn_name].setFixedHeight(35)
            # self.__dict__[btn_name].setHidden(True)
            self.layout_btn.addWidget(self.__dict__[btn_name])


        self.grid_main.addWidget(self.sidebar, 0, 0)
        self.grid_main.addWidget(self.content, 0, 1)
        self.grid_main.addWidget(self.QDivider(self), 1, 0, 1, 2)
        self.grid_main.addLayout(self.layout_btn, 2, 0, 1, 2)

        # self.grid_main.setColumnStretch(0, 1)
        # self.grid_main.setColumnStretch(1, 3)
        self.sidebar.setFixedWidth(150)

    def QStorageBand(self, parent, grid, items):
        self.STANDARD_KEY = QtWidgets.QLineEdit(parent)
        self.STANDARD_KEY.setPlaceholderText('')

        self.STANDARD_NAME_LIST = QtWidgets.QComboBox(parent)
        self.STANDARD_NAME_LIST.setStyleSheet("""
                QComboBox{
                    height: 30px;
                  font-size:14px;
                } 
                QComboBox::drop-down {                      
                    image: none;                      
                }
        """)

        self.STANDARD_NAME_LIST.setEditable(True)
        self.STANDARD_NAME_LIST.addItems(items)
        self.STANDARD_KEY_LIST = QtWidgets.QComboBox(parent)
        self.STANDARD_KEY_LIST.addItem('空')

        self.BTN_STD_SAVE = QtWidgets.QPushButton('保存配方', parent)
        self.BTN_STD_LOAD = QtWidgets.QPushButton('加载配方', parent)
        self.BTN_STD_DEL = QtWidgets.QPushButton('删除配方', parent)
        button_style = """
            QPushButton {
                background-color: rgb(0,175,219);
                color: white;
                border-radius: 5px;
                padding: 10px 20px;
                border-width: 5px;
                border-color: rgb(108, 166, 205);
                border-style: outset;
            }
            QPushButton:hover {background-color: rgb(108, 166, 205);}
            QPushButton:pressed {background-color: rgb(74, 112, 139);}
        """

        # self.BTN_STD_SAVE.setStyleSheet(button_style + """
        #     QPushButton:enabled {background-color: rgb(0,175,219);}
        #     QPushButton:disabled {background-color: rgb(128,128,128);}
        # """)

        self.BTN_STD_SAVE.setStyleSheet(button_style)

        self.BTN_STD_LOAD.setStyleSheet(button_style)

        self.BTN_STD_DEL.setStyleSheet(button_style)

        self.layout_standard_up = QtWidgets.QHBoxLayout()
        self.layout_standard_up.addWidget(self.STANDARD_NAME_LIST, 2)
        self.layout_standard_up.addWidget(self.STANDARD_KEY, 1)
        self.layout_standard_up.addWidget(self.BTN_STD_SAVE, 1)

        self.layout_standard_down = QtWidgets.QHBoxLayout()
        self.layout_standard_down.addWidget(self.STANDARD_KEY_LIST, 2)
        self.layout_standard_down.addWidget(self.BTN_STD_LOAD, 1)
        self.layout_standard_down.addWidget(self.BTN_STD_DEL, 1)

        self.layout_standard = QtWidgets.QVBoxLayout()
        self.layout_standard.addLayout(self.layout_standard_up,0)
        self.layout_standard.addLayout(self.layout_standard_down,1)

        grid.addLayout(self.layout_standard, 1, 0)

    def QControlItem(self, parent, grid, var, text):
        """ 检测控制中的单个条目 """

        def __QSpinBox(var, parent):
            spinbox_name = '%s' % var.upper()  # num scope
            setattr(self, spinbox_name, QtWidgets.QSpinBox(parent))
            spinbox_obj: QtWidgets.QSpinBox = getattr(self, spinbox_name)
            spinbox_obj.setFixedSize(160, 35)
            spinbox_obj.setMinimum(1)
            spinbox_obj.setMaximum(9999999)
            return spinbox_obj

        def __QScope(var, text, parent):
            splitter_obj = self.QSplitterPack('splitter_num_%s' % var, parent)
            splitter_obj.setHandleWidth(3)

            radio_name = '%s_NUM' % var.upper()  # num
            setattr(self, radio_name, QtWidgets.QRadioButton(text, parent))
            radio_obj: QtWidgets.QRadioButton = getattr(self, radio_name)

            splitter_obj.addWidget(radio_obj)
            splitter_obj.addWidget(QtWidgets.QLabel('从', parent))
            splitter_obj.addWidget(__QSpinBox('%s_num_begin' % var, parent))
            splitter_obj.addWidget(QtWidgets.QLabel('到', parent))
            splitter_obj.addWidget(__QSpinBox('%s_num_end' % var, parent))
            splitter_obj.setStretchFactor(0, 1)

            return radio_obj, splitter_obj


        var = var.lower()
        # setattr(self, var.upper().replace('UI_KEY_', ''), True)  # 总开关 默认开启

        splitter_obj = self.QSplitterPack('splitter_%s' % var, parent, Qt.Vertical)
        splitter_obj.setHandleWidth(3)

        splitter_title_obj = self.QSplitterPack('splitter_title_%s' % var, parent)
        splitter_title_obj.setHandleWidth(3)
        combo_name = '%s_CTRL_STATUS' % var.upper() # status
        setattr(self, combo_name, QtWidgets.QComboBox(parent))
        combo_obj: QtWidgets.QComboBox = getattr(self, combo_name)
        combo_obj.addItems(['关闭', '开启'])
        combo_obj.setCurrentIndex(1)
        combo_obj.setFixedSize(160, 35)
        label_name = 'label_%s' % var
        setattr(self, label_name, QtWidgets.QLabel('%s' % text, parent))
        label_obj: QtWidgets.QLabel = getattr(self, label_name)
        label_obj.setAlignment(Qt.AlignCenter)
        label_obj.setStyleSheet('border: 2px inset gray')
        font = QFont()
        font.setBold(True)
        font.setPointSize(15)
        label_obj.setFont(font)
        splitter_title_obj.addWidget(label_obj)
        splitter_title_obj.addWidget(combo_obj)
        # splitter_title_obj.setStretchFactor(1, 1)

        radio_num_obj, splitter_num_obj = __QScope(var, '计数：', parent)
        radio_time_obj, splitter_time_obj = self.QPeriodBand(var, '定时：', parent)

        # btn_group_name = 'btn_group_%s' % var
        # setattr(self, btn_group_name, QtWidgets.QButtonGroup(parent))
        # btn_group_obj: QtWidgets.QButtonGroup = getattr(self, btn_group_name)
        # btn_group_obj.addButton(radio_num_obj)
        # btn_group_obj.addButton(radio_time_obj)

        splitter_obj.addWidget(splitter_title_obj)
        splitter_obj.addWidget(splitter_num_obj)
        splitter_obj.addWidget(splitter_time_obj)

        grid.addWidget(splitter_obj)

    def QCamBaslerBand(self, parent, grid):
        """ basler相机 """
        self.QDuet(parent, grid, (QtWidgets.QLabel, QtWidgets.QComboBox), 'CAM_SWITCH', text='相机位置', items=['正面', '侧面', '背面'], line=True)
        for var, scope in [
            ('UI_KEY_CAM_GainRaw', (300, 850)),
            ('UI_KEY_CAM_BlackLevelRaw', (0, 1023)),
            ('UI_KEY_CAM_ExposureTimeRaw', (16, 1000000)),
        ]:
            self.QDuet(parent, grid, (QtWidgets.QLabel, QtWidgets.QSpinBox), var, scope=scope, text=var.replace('UI_KEY_CAM_', ''), line=True)
        for var, items in [
            ('UI_KEY_CAM_Trigger', ['Off', 'RisingEdge', 'FallingEdge']),
            ('UI_KEY_CAM_LightSourceSelector', ['Off', 'Daylight', 'Tungsten', 'Daylight6500K']),
        ]:
            self.QDuet(parent, grid, (QtWidgets.QLabel, QtWidgets.QComboBox), var, items=items,text=var.replace('UI_KEY_CAM_', ''), line=True)

        splitter_gamma_r = self.QSplitterPack('gamma_r', parent, Qt.Vertical)
        splitter_gamma_r.setHandleWidth(3)
        self.UI_KEY_CAM_GAMMA_0 = QtWidgets.QComboBox(parent)
        self.UI_KEY_CAM_GAMMA_0.addItems(['Off', 'sRGB', 'User'])
        self.UI_KEY_CAM_GAMMA_0.setFixedSize(150, 35)
        self.UI_KEY_CAM_GAMMA_1 = QtWidgets.QDoubleSpinBox(parent)
        self.UI_KEY_CAM_GAMMA_1.setMinimum(0.0)
        self.UI_KEY_CAM_GAMMA_1.setMaximum(1.0)
        self.UI_KEY_CAM_GAMMA_1.setDecimals(5)
        self.UI_KEY_CAM_GAMMA_1.setFixedSize(150, 35)
        self.UI_KEY_CAM_GAMMA_1.setEnabled(False)
        splitter_gamma_r.addWidget(self.UI_KEY_CAM_GAMMA_0)
        splitter_gamma_r.addWidget(self.UI_KEY_CAM_GAMMA_1)

        splitter_gamma = self.QSplitterBand(
            QtWidgets.QLabel('Gamma'),
            splitter_gamma_r,
            var = 'gamma',
            parent = parent
        )
        grid.addWidget(splitter_gamma)
        grid.addWidget(self.QDivider(parent))

        self.layout_cam_btn = QtWidgets.QHBoxLayout()
        self.BTN_CAM_SAVE = QtWidgets.QPushButton('保存当前配置', parent)
        self.BTN_CAM_RESET = QtWidgets.QPushButton('恢复出厂设置', parent)
        self.BTN_CAM_SAVE.setFixedHeight(35)
        self.BTN_CAM_RESET.setFixedHeight(35)
        self.layout_cam_btn.addWidget(self.BTN_CAM_SAVE)
        self.layout_cam_btn.addWidget(self.BTN_CAM_RESET)
        grid.addLayout(self.layout_cam_btn, grid.count(), 0)


    def _initConf(self):
        """ 初始化用户配置文件 """
        # 初始化IPC_KEYS 用于UI与其他线程的通信
        self.ipc_dict.update({k: self.GetValue(self.__dict__[k]) for k in self.__dict__ if k.startswith('UI_KEY_')})
        # print(self.ipc_dict)  # TEST

        if not os.path.exists(self.conf):
            conf = BASE_PATH / 'ui/default_settings.py'
            if conf.exists():
                print('* 使用默认配置初始化用户配置')  # TEST
                data = conf.read_text('utf-8')
                data = json.loads(data)
            else:
                print('* 使用原始配置初始化用户配置')  # TEST
                # data = self.ipc_dict.copy()
                data = {k: v for k, v in self.ipc_dict.items() if k.startswith('UI_KEY_')}
            write_conf(data, self.conf)

    def _overwrite(self, data):
        """ 用配置文件中已存在的数据覆写界面上的数据 """
        # print('当前参数', data)  # TEST
        if not data:
            return
        for k, v in self.ipc_dict.items():
            if k in data:
                v = data[k]
                self.ipc_dict[k] = v
            if k in self.__dict__:
                self.SetValue(self.__dict__[k], v)

    def _if_change(self):
        """ 检查是否有发生改变的参数 """
        if not self.conf:
            return False
        for k, v in self.ipc_dict.items():
            if k.startswith('UI_KEY_') and k in self.__dict__:
                ui_v = self.GetValue(self.__dict__[k])
                if v != ui_v:
                    print('本次修改参数：', k, '|', 'IPC:', v, 'UI:', ui_v)  # TEST
                    self.changed_keys.update({ k: ui_v })
        if self.changed_keys:
            return True
        else:
            return False

    def _save(self):
        ret = self._if_change()
        if not ret:
            QtWidgets.QMessageBox.information(self, '提示', '您未作任何修改 无需保存 ～')
            return

        data = self.changed_keys
        for k, v in self.changed_keys.items():
            self.ipc_dict[k] = v  # ipc
        self._update_ui()  # ui
        try:
            # print('本次修改的参数', data)  # TEST
            write_conf(data, self.conf)  # user
            self.save()  # 派生类重写
            if [k for k in data if k.endswith('_REBOOT')]:
                reply = QtWidgets.QMessageBox.information(self, '提示', '保存成功！\n部分参数重启后生效，是否立即重启？', QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
                if reply == QtWidgets.QMessageBox.Yes:
                    restart_app(os.getpid(), BASE_PATH)
            else:
                QtWidgets.QMessageBox.information(self, '提示', '保存成功！')
        except Exception as e:
            print('Error:', e)
            QtWidgets.QMessageBox.warning(self, '提示', '保存失败！请重试')
        self.changed_keys = {}
        self.close()

    def _update_ui(self):
        """ 更新UI主界面 """
        self.update_ui()
        ui_keys = {}
        self.ui_buffer.put(ui_keys) if ui_keys and self.ui_buffer else None

    def _cam_debug(self):
        """ 相机调试提示框 """
        tips = '''
            我们已将相机参数调至最佳～<br>
            随意修改可能引发<span style="color: red"><u>严重问题</u></span>导致检测模型不能工作！<br>
            如果您仍要修改，请确定后点击右下角设置进入相机调试模式
        '''
        Yes = QPushButton('确定')
        No = QPushButton('取消')
        msg = self.QTimedPopover(self, QtWidgets.QMessageBox.Question, '警告！(30秒后自动取消)', tips, 30, Yes, No, 'No')
        if msg == No:
            # NOTE 在showEvent中应使用QTimer/QMetaObject调用close函数 以此留出时间让内部标识正确更新 否则会出现错误使窗口不能正常关闭
            QTimer.singleShot(0, self.close)

    @pyqtSlot()
    def cam_save(self):
        """ 存储相机配置 """
        conf = self.cam_conf_path / ('cam%d.json' % self.CAM_SWITCH.currentIndex())
        items = {key: self.GetValue(self.__dict__[key]) for key in self.__dict__ if key.startswith('UI_KEY_CAM_')}
        with open(conf, 'w') as f:
            json.dump(items, f)
        QtWidgets.QMessageBox.information(self, '提示', '保存成功~')
        print('已将当前相机配置保存在', conf)

    @pyqtSlot()
    def cam_reset(self):
        """ 还原相机配置 """
        conf = self.cam_conf_path / ('cam%d.json' % self.CAM_SWITCH.currentIndex())
        with open(conf, 'r') as f:
            data = json.load(f)
        try:
            _ = [self.SetValue(self.__dict__[k], v) for k, v in data.items()]
            QtWidgets.QMessageBox.information(self, '提示', '还原成功~')
        except Exception as e:
            print('Error', e)
            QtWidgets.QMessageBox.information(self, '提示', '还原失败~')

    @pyqtSlot()
    def std_save(self):
        if not self.STANDARD_KEY.text():
            QtWidgets.QMessageBox.information(self, '提示', '名称不能为空！')
            return
        name, key = self.STANDARD_NAME_LIST.currentText(), self.STANDARD_KEY.text()
        std_data = {k: self.GetValue(self.__dict__[k]) for pre in self.standard_keys for k in self.__dict__ if k.startswith(pre)}
        key_list = self.cursor.execute('SELECT KEY FROM STANDARD_DATA WHERE NAME=?', (name,)).fetchall()
        flag = key_list and key in [item for sub in key_list for item in sub]
        if flag:

            sql = 'UPDATE STANDARD_DATA SET VALUE=? WHERE NAME=? AND KEY=?'
            args = (str(std_data), name, key)
        else:

            sql = 'INSERT INTO STANDARD_DATA VALUES (?, ?, ?)'
            args = (name, key, str(std_data))
        try:
            self.cursor.execute(sql, args)
            self.conn.commit()
            self.std_query()

            self.STANDARD_KEY_LIST.setCurrentText(key)
            self.STANDARD_KEY.setText(key)
            self._save()
        except Exception as e:

            print('Error', e)
            QtWidgets.QMessageBox.information(self, '提示', '保存失败～')

    @pyqtSlot()
    def std_load(self, key=None):

        sql = 'SELECT VALUE FROM STANDARD_DATA WHERE NAME=? AND KEY=?'
        key = self.STANDARD_KEY_LIST.currentText() if not key or False else key

        if key not in [self.STANDARD_KEY_LIST.itemText(i) for i in range(self.STANDARD_KEY_LIST.count())]:
            return

        key = key if key else self.STANDARD_KEY_LIST.currentText()
        try:

            data = self.cursor.execute(sql, (self.STANDARD_NAME_LIST.currentText(), key)).fetchone()[0]
            _ = [self.SetValue(self.__dict__[k], v) for k, v in eval(data).items()]
            self.STANDARD_KEY.setText(self.STANDARD_KEY_LIST.currentText())
            self.UI_KEY_STAND_NAME.setText(self.STANDARD_KEY_LIST.currentText())
        except Exception as e:

            print('Error', e)

    @pyqtSlot()
    def std_del(self):
        sql = 'DELETE FROM STANDARD_DATA WHERE NAME=? AND KEY=?'
        try:
            self.cursor.execute(sql, (self.STANDARD_NAME_LIST.currentText(), self.STANDARD_KEY_LIST.currentText()))
            self.conn.commit()
            self.std_query()
            QtWidgets.QMessageBox.information(self, '提示', '删除成功～')
        except Exception as e:
            print('Error', e)
            QtWidgets.QMessageBox.information(self, '提示', '删除失败～')

    @pyqtSlot()
    def std_query(self):
        current_text = self.STANDARD_NAME_LIST.currentText()
        sql = 'SELECT NAME FROM STANDARD_DATA'
        try:
            data = self.cursor.execute(sql).fetchall()
            data = [item for sub in data for item in sub]
            if data:
                items = [self.STANDARD_NAME_LIST.itemText(i) for i in range(self.STANDARD_NAME_LIST.count())]
                items = list(set(items + data))
                self.STANDARD_NAME_LIST.clear()
                self.STANDARD_NAME_LIST.addItems(items)
                self.STANDARD_NAME_LIST.setCurrentText(current_text)
        except Exception as e:
            print('Error', e)
        sql = 'SELECT KEY FROM STANDARD_DATA WHERE NAME=?'
        try:
            data = self.cursor.execute(sql, (current_text, )).fetchall()
            data = [item for sub in data for item in sub]
            if not data:
                data = ['空']
            self.STANDARD_KEY_LIST.clear()
            self.STANDARD_KEY_LIST.addItems(data)
            key = self.UI_KEY_STAND_NAME.text().split('/')[-1]

            for i in range(self.STANDARD_KEY_LIST.count()):
                if key == self.STANDARD_KEY_LIST.itemText(i):
                    self.STANDARD_KEY_LIST.setCurrentText(key)
                    self.STANDARD_KEY.setText(key)
        except Exception as e:
            print('Error', e)


    @property
    def ui_model_usage(self):
        """ 模型开关 """
        keys = [k for k in self.__dict__ if re.fullmatch(r'UI_KEY_CAM\d+(_REBOOT)?', k)]
        keys.sort(key=lambda x: x[-1])
        return [int(self.GetValue(self.__dict__[k])) if self.GetValue(self.__dict__[k]).isdigit() else -1 for k in keys]

    @ui_model_usage.setter
    def ui_model_usage(self, values: list):
        keys = [k for k in self.__dict__ if re.fullmatch(r'UI_KEY_CAM\d+(_REBOOT)?', k)]
        keys.sort(key=lambda x: x[-1])
        for k, v in zip(keys, values):
            self.SetValue(self.__dict__[k], v)

    @property
    def ui_cam_sn(self):
        keys = [k for k in self.__dict__ if re.fullmatch(r'UI_KEY_SN\d+(_REBOOT)?', k)]
        keys.sort(key=lambda x: x[-1])
        return [self.GetValue(self.__dict__[k]) if self.GetValue(self.__dict__[k]) and self.GetValue(self.__dict__['UI_KEY_SN%d_SWITCH_REBOOT' % i]) else None for i, k in enumerate(keys)]

    @ui_cam_sn.setter
    def ui_cam_sn(self, values: list):
        keys = [k for k in self.__dict__ if re.fullmatch(r'UI_KEY_SN\d+(_REBOOT)?', k)]
        keys.sort(key=lambda x: x[-1])
        for k, v in zip(keys, values):
            self.SetValue(self.__dict__[k], v)


    # 根据项目需求在派生类中重写以下函数

    def p0_custom(self, parent, grid):
        """ 通用 """
        for item in [
            ('UI_KEY_FLAG_SAVE_ORI_IMG', '保存原图'),
            ('UI_KEY_FLAG_SAVE_DET_IMG', '保存检测图'),
        ]:
            self.QDuet(parent, grid, (QtWidgets.QLabel, QtWidgets.QCheckBox), *item)

    def p1_custom(self, parent, grid):
        """ 模型0 """
        pass

    def p2_custom(self, parent, grid):
        """ 模型1 """
        pass

    def p3_custom(self, parent, grid):
        """ 模型2 """
        pass

    def p4_custom(self, parent, grid):
        """ 标准 """
        pass

    def p5_custom(self, parent, grid):
        """ 硬件 """
        pass

    def p6_custom(self, parent, grid):
        """ 相机 """
        self.QCamBaslerBand(parent, grid)

    def p7_custom(self, parent, grid):
        """ 控制 """
        pass

    def p8_custom(self, parent, grid):
        """ 检测 """
        pass

    def update_ui(self):
        """ 更新UI主界面 """
        ui_keys = {}
        self.ui_buffer.put(ui_keys) if ui_keys and self.ui_buffer else None

    def save(self):
        """ 保存 """
        pass

